package sessionKey

/*
    #cgo CFLAGS: -I../
    #cgo LDFLAGS: -L../ -ldecd -lm
	#include "compute.h"
	#include "device.h"
	#include "key.h"
	#include "manager.h"
	#include "xdma.h"
    #include <stdlib.h>
*/
import "C"
import (
	"encoding/hex"
	"errors"
	"fmt"
	"strings"
	"unsafe"
)

// 生成同态公私钥对
func FHEKmg_Create_FheKey(FHE_Key_Index uint) (string, string, error) {
	var err error         // 出错返回值
	var ret_pubkey string // 功能返回密钥值
	var ret_prikey string // 功能返回密钥值
	ret_pubkey = ""
	ret_prikey = ""
	bt_pubkey := make([]byte, 524288+1)      // 给bt变量复制524288个字节
	FHE_pubKey := GetBytePointer1(bt_pubkey) //用CGO语言进行强制类型转换字符
	bt_prikey := make([]byte, 129)           // 给bt变量复制524288个字节
	FHE_priKey := GetBytePointer1(bt_prikey) //用CGO语言进行强制类型转换字符
	FHE_Key_Index1 := C.uint(FHE_Key_Index)  // CGO类型转换
	rv := C.FHEKmg_Create_And_Backup_FheKeyPair(FHE_Key_Index1, FHE_pubKey, FHE_priKey)
	if rv != 0 {
		cw := fmt.Sprintf("%x", rv)
		err = errors.New("出错信息:生成同态公私钥对时出错！错误号：" + cw)
		return ret_pubkey, ret_prikey, err
	}
	ret_pubkey = C.GoStringN(FHE_pubKey, 524288+1) // 取出同态公私钥对值
	ret_prikey = C.GoStringN(FHE_priKey, 129)      // 取出同态公私钥对值
	return ret_pubkey, ret_prikey, nil
}

// 导入同态公私钥对
func NFHE_DECD_Import_FHE_Key(FHE_Key_Index uint, FHEPubKey []byte, FHEPrikey []byte) error {
	var err error                                                                 // 出错返回值
	FHEPubKeyTmpStr := hex.EncodeToString(FHEPubKey)[0:524288]                    // 将byte转换字符串
	FHEPubKeyTmpStr1 := C.CString(FHEPubKeyTmpStr)                                // 将go字符串转换C字符串
	var FHEPubKeyTmp = (*C.char)(unsafe.Pointer(FHEPubKeyTmpStr1))                // 将C字符串转换C.char指针
	defer C.free(unsafe.Pointer(FHEPubKeyTmpStr1))                                // 动态回收内存空间
	FHEPriKeyTmpStr := hex.EncodeToString(FHEPrikey)[0:64]                        // 将byte转换字符串
	FHEPriKeyTmpStr1 := C.CString(FHEPriKeyTmpStr)                                // 将go字符串转换C字符串
	var FHEPriKeyTmp = (*C.char)(unsafe.Pointer(FHEPriKeyTmpStr1))                // 将C字符串转换C.char指针
	defer C.free(unsafe.Pointer(FHEPriKeyTmpStr1))                                // 动态回收内存空间
	FHE_Key_Index1 := C.uint(FHE_Key_Index)                                       // CGO类型转换
	rv := C.FHEKmg_Restore_FheKeyPair(FHE_Key_Index1, FHEPubKeyTmp, FHEPriKeyTmp) // 导入同态公私钥对
	if rv != 0 {
		cw := fmt.Sprintf("%x", rv)
		err = errors.New("出错信息:导入同态公私钥对出错！错误号：" + cw)
	} else {
		rv = C.FHEKmg_LoadFhePriKey(1)
		return nil
	}
	return err
}

//// 备份同态私钥
//func FHEKmg_Backup_FhePriKey(FHE_Key_Index uint) (string, error) {
//	var err error                           // 出错返回值
//	var ret string                          // 功能返回密钥值
//	bt := make([]byte, 129)                 // 给bt变量复制65个字节
//	FHE_PriKey := GetBytePointer1(bt)       //用CGO语言进行强制类型转换字符
//	FHE_Key_Index1 := C.uint(FHE_Key_Index) // CGO类型转换
//	rv := C.FHEKmg_BackupFHEPriKey(FHE_Key_Index1, FHE_PriKey)
//	if rv != 0 {
//		cw := fmt.Sprintf("%x", rv)
//		err = errors.New("出错信息:生成同态公私钥对时出错！错误号：" + cw)
//	} else {
//		ret = C.GoStringN(FHE_PriKey, 64) // 取出同态私钥值
//		return ret, nil
//	}
//	return ret, err
//}
//
//// 恢复同态私钥
//func FHEKmg_Restore_FhePriKey(FHE_Key_Index uint, FHE_PriKey []byte) error {
//	var err error                                                    // 出错返回值
//	FHE_Key_Index1 := C.uint(FHE_Key_Index)                          // CGO类型转换
//	FHE_PriKeyTmpStr := hex.EncodeToString(FHE_PriKey)[0:64]         // 将byte转换字符串
//	FHE_PriKeyTmpStr1 := C.CString(FHE_PriKeyTmpStr)                 // 将go字符串转换C字符串
//	var FHE_PriKeyTmp = (*C.char)(unsafe.Pointer(FHE_PriKeyTmpStr1)) // 将C字符串转换C.char指针
//	defer C.free(unsafe.Pointer(FHE_PriKeyTmpStr1))                  // 动态回收内存空间
//	rv := C.FHEKmg_RestoreFHEPriKey(FHE_Key_Index1, FHE_PriKeyTmp)   // 恢复加密卡的设备主密钥
//	if rv != 0 {
//		cw := fmt.Sprintf("%x", rv)
//		err = errors.New("出错信息:恢复同态私钥钥时出错！错误号：" + cw)
//	} else {
//		return nil
//	}
//	return err
//}

// 生成SM1密钥
func NFHE_DECD_Create_SM1(SM1_Key_Index uint) error {
	var err error                                // 出错返回值
	SM1_Key_Index1 := C.uint(SM1_Key_Index)      // CGO类型转换
	rv := C.FHEKmg_Create_Sm1key(SM1_Key_Index1) // 生成SM1密钥
	if rv != 0 {
		cw := fmt.Sprintf("%x", rv)
		err = errors.New("出错信息:生成SM1密钥时出错！错误号：" + cw)
	} else {
		return nil
	}
	return err
}

// 备份SM1密钥
func NFHE_DECD_Backup_SM1(SM1_Key_Index uint) (string, error) {
	var err error                                            // 出错返回值
	var ret string                                           // 功能返回密钥值
	bt := make([]byte, 16)                                   // 给bt变量复制16个字节
	Ls_SM1_key := GetCharPointer(bt)                         //用CGO语言进行强制类型转换字符
	SM1_Key_Index1 := C.uint(SM1_Key_Index)                  // CGO类型转换
	rv := C.FHEKmg_Backup_Sm1key(SM1_Key_Index1, Ls_SM1_key) // 备份SM1密钥
	if rv != 0 {
		cw := fmt.Sprintf("%x", rv)
		err = errors.New("出错信息:备份SM1时出错！错误号：" + cw)
	} else {
		ret = C.GoStringN(Ls_SM1_key, 32) // 取出SM1密钥值
	}
	return ret, err
}

// 恢复SM1密钥
func NFHE_DECD_Restore_SM1(SM1_Key_Index uint, Ls_SM1 []byte) error {
	var err error                                              // 出错返回值
	Ls_SM1_Str := hex.EncodeToString(Ls_SM1)[0:32]             // 将byte转换字符串
	Ls_SM1_Str1 := C.CString(Ls_SM1_Str)                       // 将go字符串转换C字符串
	var Ls_SM1_StrTmp = (*C.char)(unsafe.Pointer(Ls_SM1_Str1)) // 将C字符串转换C.char指针
	defer C.free(unsafe.Pointer(Ls_SM1_Str1))                  // 动态回收内存空间
	KEKIndex1 := C.uint(SM1_Key_Index)                         // CGO类型转换
	rv := C.FHEKmg_Restore_Sm1key(KEKIndex1, Ls_SM1_StrTmp)    // 恢复SM1密钥
	if rv != 0 {
		cw := fmt.Sprintf("%x", rv)
		err = errors.New("出错信息:恢复SM1时出错！错误号：" + cw)
	} else {
		return nil
	}
	return err
}

// 生成SM2密钥
func FHESdf_Create_Sm2key() error {
	var err error                  // 出错返回值
	rv := C.FHESdf_Create_Sm2key() // 生成SM2密钥
	if rv != 0 {
		cw := fmt.Sprintf("%x", rv)
		err = errors.New("出错信息:生成SM2密钥时出错！错误号：" + cw)
	} else {
		return nil
	}
	return err
}

// 备份SM2密钥
func FHESdf_Backup_Sm2key() (string, string, error) {
	var err error                                                 // 出错返回值
	var retPublicKey, retPrivateKey string                        // 功能返回密钥值
	PublicKeyByte := make([]byte, 129)                            // 给bt变量复制16个字节
	PublicKeyByte1 := GetCharPointer(PublicKeyByte)               //用CGO语言进行强制类型转换字符
	PrivateKeyByte := make([]byte, 65)                            // 给bt变量复制16个字节
	PrivateKeyByte1 := GetCharPointer(PrivateKeyByte)             //用CGO语言进行强制类型转换字符
	rv := C.FHESdf_Backup_Sm2key(PublicKeyByte1, PrivateKeyByte1) // 备份SM2公钥和私钥
	if rv != 0 {
		cw := fmt.Sprintf("%x", rv)
		err = errors.New("出错信息:备份SM2密钥时出错！错误号：" + cw)
	} else {
		retPublicKey = strings.ToUpper(string(PublicKeyByte))   //C.GoStringN(retPublicKey, 512)   // 取出SM1密钥值
		retPrivateKey = strings.ToUpper(string(PrivateKeyByte)) //C.GoStringN(retPrivateKey, 512) // 取出SM1密钥值
	}
	return retPublicKey, retPrivateKey, err
}

// 恢复SM2密钥
func FHESdf_Restore_Sm2key(PublicKey []byte, PrivateKey []byte) error {
	var err error                                                              // 出错返回值
	SM2_PublicKey_Str := hex.EncodeToString(PublicKey)[0:128]                  // 将byte转换字符串
	SM2_PublicKey_Str1 := C.CString(SM2_PublicKey_Str)                         // 将go字符串转换C字符串
	var SM2_PublicKey_StrTmp = (*C.char)(unsafe.Pointer(SM2_PublicKey_Str1))   // 将C字符串转换C.char指针
	defer C.free(unsafe.Pointer(SM2_PublicKey_Str1))                           // 动态回收内存空间
	SM2_PrivateKey_Str := hex.EncodeToString(PrivateKey)[0:64]                 // 将byte转换字符串
	SM2_PrivateKey_Str1 := C.CString(SM2_PrivateKey_Str)                       // 将go字符串转换C字符串
	var SM2_PrivateKey_StrTmp = (*C.char)(unsafe.Pointer(SM2_PrivateKey_Str1)) // 将C字符串转换C.char指针
	defer C.free(unsafe.Pointer(SM2_PrivateKey_Str1))                          // 动态回收内存空间

	rv := C.FHESdf_Restore_Sm2key(SM2_PublicKey_StrTmp, SM2_PrivateKey_StrTmp) // 恢复SM2密钥
	if rv != 0 {
		cw := fmt.Sprintf("%x", rv)
		err = errors.New("出错信息:恢复SM1时出错！错误号：" + cw)
	} else {
		return nil
	}
	return err
}

// 生成用户权限口令
func NFHE_DECD_Create_Auth(SM1_Key_Index uint) error {
	var err error                                 // 出错返回值
	SM1_Key_Index1 := C.uint(SM1_Key_Index)       // CGO类型转换
	rv := C.FHEKmg_Create_FheAuth(SM1_Key_Index1) // 生成用户权限口令
	if rv != 0 {
		cw := fmt.Sprintf("%x", rv)
		err = errors.New("出错信息:生成用户权限口令时出错！错误号：" + cw)
	} else {
		return nil
	}
	return err
}

// 备份用户权限口令
func NFHE_DECD_Backup_Auth(SM1_Key_Index uint) (string, error) {
	var err error                                             // 出错返回值
	var ret string                                            // 功能返回密钥值
	bt := make([]byte, 16)                                    // 给bt变量复制16个字节
	Ls_SM1_key := GetCharPointer(bt)                          //用CGO语言进行强制类型转换字符
	SM1_Key_Index1 := C.uint(SM1_Key_Index)                   // CGO类型转换
	rv := C.FHEKmg_Backup_FheAuth(SM1_Key_Index1, Ls_SM1_key) // 备份用户权限口令
	if rv != 0 {
		cw := fmt.Sprintf("%x", rv)
		err = errors.New("出错信息:备份用户权限口令时出错！错误号：" + cw)
	} else {
		ret = C.GoStringN(Ls_SM1_key, 32) // 取出SM1密钥值
		return ret, nil
	}
	return ret, err
}

// 恢复用户权限口令
func NFHE_DECD_Restore_Auth(SM1_Key_Index uint, Ls_SM1 []byte) error {
	var err error                                              // 出错返回值
	Ls_SM1_Str := hex.EncodeToString(Ls_SM1)[0:32]             // 将byte转换字符串
	Ls_SM1_Str1 := C.CString(Ls_SM1_Str)                       // 将go字符串转换C字符串
	var Ls_SM1_StrTmp = (*C.char)(unsafe.Pointer(Ls_SM1_Str1)) // 将C字符串转换C.char指针
	defer C.free(unsafe.Pointer(Ls_SM1_Str1))                  // 动态回收内存空间
	KEKIndex1 := C.uint(SM1_Key_Index)                         // CGO类型转换
	rv := C.FHEKmg_Restore_FheAuth(KEKIndex1, Ls_SM1_StrTmp)   // 恢复用户权限口令
	if rv != 0 {
		cw := fmt.Sprintf("%x", rv)
		err = errors.New("出错信息:恢复用户权限口令时出错！错误号：" + cw)
	} else {
		return nil
	}
	return err
}

// 将cgo的字节转换为c语言字节
func GetBytePointer(val []byte) *C.uchar {
	return (*C.uchar)(unsafe.Pointer(&val[0]))
}

// 将cgo的字节转换为c语言字节
func GetBytePointer1(val []byte) *C.char {
	return (*C.char)(unsafe.Pointer(&val[0]))
}

// 转换字节为字符指针
func GetCharPointer(val []byte) *C.char {
	return (*C.char)(unsafe.Pointer(&val[0]))
}
